//---------------------------------------------------------------------------

#ifndef BFIExpressionH
#define BFIExpressionH

#include "BFISymbol.h"
#include <vector.h>
#include <map.h>

        typedef struct {
                bool inversion;
                int x;
                int y;
                String key;
        } BooleanCharacter;
        typedef vector<BooleanCharacter*> Characters;
        typedef Characters::iterator iCharacters;
        struct Leaf {
                Leaf* parent;
                Leaf* right;
                Leaf* left;
//              Characters data;
                Characters::iterator start;
                Characters::iterator end;
                int i;//Type of separator: 0 - or, 1 - and
                int level;

                bool leftBrackets;
                bool rightBrackets;
        } ;
        typedef vector<Leaf*> Leafs;
        typedef Leafs::iterator iLeafs;
        typedef map<int,Leafs*> Levels;
        typedef Levels::iterator iLevels;
        typedef map<Characters*,Characters*> Rules;
        typedef Rules::iterator iRules;
        typedef struct {
                Leaf* rulesRoots;
                Levels* levels;
        } RulesRoots;
        typedef map<RulesRoots*,RulesRoots*> RulesRootsMap;
        typedef RulesRootsMap::iterator iRulesMap;
        typedef map<BooleanCharacter*,Characters*> Net;
        typedef Net::iterator iNet;
class BFIExpression
{
        Characters operations;
        private:
//              typedef map<String,BFISymbol*> Characters;
//              typedef map<int,int> Koordinates;
//              typedef map<int,bool> Inversions;
                typedef map<String,String> Keys;
//              vector<String/*BFISymbol**/> symbols;
//              Characters characters;
//              map<int,Koordinates> koordinates;
//              Inversions inversions;
                TImage* image;
                TScrollBox* scrollBox;
                bool lastIsOperation;
                int x,y;
                static int border;
                static map<String,String> keys;
                vector<String> priorities;
                Rules rules;
                map<String,Characters*> changes;

                Leaf* root;
//              map<Leaf*,Leaf*> rulesRoots;
//        vector<RulesRoots*> rulesRoots;
                RulesRootsMap* rulesRoots;
//              Characters* vectorNew;
//              Characters* left;// = new Characters;
//              Characters* right;// = new Characters;

        public:

                Characters characters;
        public:
                BFIExpression(TImage*,TScrollBox*);
                void addAND(bool = false);
                void addOR(bool = false);
                void addXOR(bool = false);
                void addEquivalence(bool = false);
                void addImplication(bool = false);
                void addConvImplication(bool = false);
                void addShefferStroke(bool = false);
                void addNOR(bool = false);
                void addPirs(bool = false);
                void addEmptySet(bool = false);
                void addUniversum(bool = false);
                void addSymbol(char,bool = false);
                void addByKey(String key,bool isInversed = false, String Character = NULL, bool add = true);
                BFIExpression* perform();
                void showError();
                static map<String,String> getKeys();
                void setXY(int x, int y);
                int getX();
                bool keyIsCharacter(String key);
                void init();
        private:
                void draw(BFISymbol* Character);
                void initRules();

                void initTree();
                bool equalVectors(Characters vector1, Characters vector2);
                bool divideCharacters(Characters::iterator start,
                        Characters::iterator end, Leaf* part1, Leaf* part2,
                        bool divUnderInversion = false);
                bool parseInversion(iCharacters start, iCharacters end);
                Leaf* findLeaf(Leaf* parent);
                String operationByID(int id);
                void addToCharacters(Characters* characters, iCharacters start, iCharacters end);
                Leaf* reloadTreeToRoot(Leaf* newLeaf);
                void initRelations(Net* net);
                bool keyInNet(BooleanCharacter* key, Net* net);
                Characters* findInNet(BooleanCharacter* key, Net* net);
                bool inversedSequence(Characters* chars);
				void buildTreeSimple(Characters* vector, Leaf* root, Leaf* parent, Levels* levels, bool parseInversions = true);
                Levels* copyLevels(Levels* toCopy);
                Leaf* createLeafIterators(Leaf* newLeaf);
        public:
                bool trimBrackets(Characters* vector, iCharacters start, iCharacters end);
                void buildTree(Characters* vector, Leaf* root, Leaf* parent, Levels* levels, bool parseInversions = true);
                void buildTreeSequence(Characters* vector, Leaf* root, Leaf* parent, Levels* levels, bool parseInversions = true);
                iCharacters findSeparator(String key, iCharacters start, iCharacters end, bool returnInversion = false);
                bool isKey(String key);
                bool equalLeaves(Leaf* rule,
//                      leaf* resultRule,
						Leaf* sequence, Net* relations
						, bool cloneRelations = false
//                      , bool replace = false
                        );
                bool equalCharacters(BooleanCharacter* char1, BooleanCharacter* char2);
                bool equalSequences(Characters* char1, Characters* char2);
                bool isCharacterInversed(BooleanCharacter* char1, BooleanCharacter* char2);
                BooleanCharacter* inverseCharacter(BooleanCharacter* char1, bool = false);
                Characters* inverseCharacters(Characters* chars);
                void inverseOperations(Leaf* root);
                void processRules(Characters* ruleIn, Characters* ruleResultIn);
                void simplifyLeaf(Leaf* leaf, Leaf* ruleTmp
                , Leaf* ruleResult, Net* relations);
                Characters getCharacters();
                Characters* getCharactersPointer();
                void setCharacters(Characters* chars);
                Characters* copyCharacters(iCharacters start, iCharacters end);
                Leaf* rebuildLeaf(Leaf* leaf, int level, Net* relations);

                void setImage(TImage* Image);
                void setScrollBox(TScrollBox* ScrollBox);

                void drawCharacters();
                void clearImage();
                void backSpace();

                bool relationsContainSequence(Characters* sequence, Net* net);

				int count;

				bool equalLeavesContent(Leaf* leaf1, Leaf* leaf2);
				Leaf* createIterators(Leaf* leaf);

				Characters* treeToCharacters(Levels* levels);
				Characters* addBrackets(Characters* chars);
				Characters* charactersFromLeaf(Leaf* leaf);

				Net* cloneNet(Net* net);
				Net* addToNet(Net* result,Net* subject);
};

//---------------------------------------------------------------------------
#endif
